#include "bigimg.h"
#include <nds.h>

#include <filesystem.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>

u32 quadTex[] =
{
17,
        FIFO_COMMAND_PACK(FIFO_BEGIN, FIFO_NORMAL, FIFO_TEX_COORD, FIFO_VERTEX16),
  GL_QUAD,
    NORMAL_PACK(0,inttov10(-1),0),
    
    TEXTURE_PACK(inttot16(0), 0),
    VERTEX_PACK(inttov16(0),inttov16(0)),
    VERTEX_PACK(0,0),
  
        FIFO_COMMAND_PACK(FIFO_TEX_COORD, FIFO_VERTEX16, FIFO_TEX_COORD, FIFO_VERTEX16),
    TEXTURE_PACK(inttot16(32), 0),
    VERTEX_PACK(inttov16(1),inttov16(0)),
    VERTEX_PACK(0,0),
  
    TEXTURE_PACK(inttot16(32), inttot16(32)),
    VERTEX_PACK(inttov16(1),inttov16(1)),
    VERTEX_PACK(0,0),   
   
        FIFO_COMMAND_PACK(FIFO_TEX_COORD, FIFO_VERTEX16, FIFO_NOP, FIFO_NOP),
    TEXTURE_PACK(inttot16(0), inttot16(32)),   
    VERTEX_PACK(inttov16(0),inttov16(1)),
    VERTEX_PACK(0,0),
};

u32 quadTex2[] =
{
12,
        FIFO_COMMAND_PACK(FIFO_BEGIN, FIFO_NORMAL, FIFO_VERTEX16, FIFO_VERTEX16),
  GL_QUAD,
    NORMAL_PACK(0,inttov10(-1),0),

    VERTEX_PACK(inttov16(0),inttov16(0)),
    VERTEX_PACK(0,0),

    VERTEX_PACK(inttov16(1),inttov16(0)),
    VERTEX_PACK(0,0),

        FIFO_COMMAND_PACK(FIFO_VERTEX16, FIFO_VERTEX16, FIFO_NOP, FIFO_NOP),
    VERTEX_PACK(inttov16(1),inttov16(1)),
    VERTEX_PACK(0,0),   
   
    VERTEX_PACK(inttov16(0),inttov16(1)),
    VERTEX_PACK(0,0),
};

void scrollTilesLeft(BigImage *img)
{
  int i,j;
  int idx = 0;

  for(j=0; j<MAP_TILES_Y; j++)
  {
    int textureTmp = img->textures[idx];
    for(i=0;i<(MAP_TILES_X-1);i++)
    {
      img->loaded[idx] = img->loaded[idx+1];
      img->textures[idx] = img->textures[idx+1];
      ++idx;
    }
    img->loaded[idx] = 0;
    img->textures[idx] = textureTmp;
    ++idx;
  }
  img->tileX++;
}

void scrollTilesRight(BigImage *img)
{
  int i,j;
  int idx = MAP_TILES_X*MAP_TILES_Y-1;

  for(j=0; j<MAP_TILES_Y; j++)
  {
    int textureTmp = img->textures[idx];
    for(i=0;i<(MAP_TILES_X-1);i++)
    {
      img->loaded[idx] = img->loaded[idx-1];
      img->textures[idx] = img->textures[idx-1];
      --idx;
    }
    img->loaded[idx] = 0;
    img->textures[idx] = textureTmp;
    --idx;
  }
  img->tileX--;
}

void scrollTilesUp(BigImage *img)
{
  int i,j;
  int idx = 0;

  for(j=0; j<MAP_TILES_X; j++)
  {
    int textureTmp = img->textures[idx];
    for(i=0;i<(MAP_TILES_Y-1);i++)
    {
      img->loaded[idx] = img->loaded[idx+MAP_TILES_X];
      img->textures[idx] = img->textures[idx+MAP_TILES_X];
      idx+=MAP_TILES_X;
    }
    img->loaded[idx] = 0;
    img->textures[idx] = textureTmp;
    idx = idx - MAP_TILES_X*(MAP_TILES_Y-1) + 1;
  }
  img->tileY++;
}

void scrollTilesDown(BigImage *img)
{
  int i,j;
  int idx = MAP_TILES_X*MAP_TILES_Y-1;

  for(j=0; j<MAP_TILES_X; j++)
  {
    int textureTmp = img->textures[idx];
    for(i=0;i<(MAP_TILES_Y-1);i++)
    {
      img->loaded[idx] = img->loaded[idx-MAP_TILES_X];
      img->textures[idx] = img->textures[idx-MAP_TILES_X];
      idx-=MAP_TILES_X;
    }
    img->loaded[idx] = 0;
    img->textures[idx] = textureTmp;
    idx = idx + MAP_TILES_X*(MAP_TILES_Y-1) - 1;
  }
  img->tileY--;
}

BigImage *createBigImage(char *fname, int tilesW, int tilesH)
{
  FILE *f = fopen(fname,"rb");
  if(!f) return 0;

  BigImage *img = (BigImage *)malloc(sizeof(BigImage));
  if(!img) {
    fclose(f);
    return 0;
  }

  img->f = f;
  img->tileX = 0;
  img->tileY = 0;
  img->sx = 0;
  img->sy = 0;
  img->widthInTiles = tilesW;
  img->heightInTiles = tilesH;

  int i;
  for(i=0;i<MAP_TILES_X*MAP_TILES_Y;i++) img->loaded[i] = 0;
  glGenTextures(MAP_TILES_X*MAP_TILES_Y,img->textures);

  return img;
}

void drawImg(BigImage *img)
{
  glPolyFmt(POLY_ALPHA(15) | POLY_CULL_NONE  );

//  glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_MODULATION | POLY_FORMAT_LIGHT0);
//  glPolyFmt(POLY_ALPHA(15) | POLY_CULL_NONE /*| POLY_MODULATION*/ );
//  glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_DECAL);
    
/*
  int i,j,idx=0;

  glTranslatef32(inttof32(img->sx), inttof32(img->sy), 0);
  glScalef32(floattof32(32),floattof32(32),0);

  for(i=0;i<MAP_TILES_Y;i++)
  {
    for(j=0;j<MAP_TILES_X;j++)
    {
      glBindTexture(0,img->textures[idx]);
      ++idx;

      glCallList(quadTex);
      glTranslatef32(inttof32(1), 0, 0);
    }
    glTranslatef32(inttof32(-9), inttof32(1), 0); 
  }
*/

  int i,j,idx=0;

  glMatrixMode(GL_TEXTURE);
  glPushMatrix();
  glLoadIdentity();
//(sz*512)/32
  glScalef32(floattof32(32*512/32),floattof32(32*512/32),0);

  glMatrixMode(GL_MODELVIEW);
  glTranslatef32(inttof32(img->sx), inttof32(img->sy), 0);
  glScalef32(floattof32(32),floattof32(32),0);

  for(i=0;i<MAP_TILES_Y;i++)
  {
    for(j=0;j<MAP_TILES_X;j++)
    {
      glBindTexture(0,img->textures[idx]);
      ++idx;
      glCallList(quadTex2);
/*
      glBegin(GL_QUAD);
        glNormal(NORMAL_PACK(0,inttov10(-1),0));
        glVertex3v16(inttov16(0),inttov16(0),0);
        glVertex3v16(inttov16(1), inttov16(0), 0);
        glVertex3v16(inttov16(1), inttov16(1), 0);
        glVertex3v16(inttov16(0), inttov16(1), 0);
      glEnd();
*/
      glTranslatef32(inttof32(1), 0, 0);
    }
    glTranslatef32(inttof32(-9), inttof32(1), 0); 
  }

  glMatrixMode(GL_TEXTURE);
  glPopMatrix(1);
  glMatrixMode(GL_MODELVIEW);

}

void loadDataFromFile(FILE *f, char *buf, int sz, int offset)
{
  fseek(f,offset,SEEK_SET);
  fread(buf,1,sz,f);
}

u16 data[TILE_SIZE_BYTES/2];
void loadTextures(BigImage *img)
{
  int i,j,idx=0;

  for(i=0;i<MAP_TILES_Y;i++)
  {
    for(j=0;j<MAP_TILES_X;j++)
    {
      if(!img->loaded[idx])
      {
        img->loaded[idx] = 1;

        int tx = img->tileX + j;
        int ty = img->tileY + i;

        while(tx<0) tx+=img->widthInTiles;
        while(tx>=img->widthInTiles) tx-=img->widthInTiles;
        while(ty<0) ty+=img->heightInTiles;
        while(ty>=img->heightInTiles) ty-=img->heightInTiles;

        int tileNum = ty*img->widthInTiles+tx;

//        char *tex = (char *)glGetTexturePointer(img->textures[idx]);
//        if(tex) {
//          loadDataFromFile(img->f,tex,TILE_SIZE_BYTES,tileNum*TILE_SIZE_BYTES);
//        } else {
          loadDataFromFile(img->f,(char *)data,TILE_SIZE_BYTES,tileNum*TILE_SIZE_BYTES);
          glBindTexture(0, img->textures[idx]);
//          glTexImage2D(0, 0, GL_RGBA, TEXTURE_SIZE_32 , TEXTURE_SIZE_32, 0, TEXGEN_TEXCOORD, data);
          glTexImage2D(0, 0, GL_RGBA, TEXTURE_SIZE_32 , TEXTURE_SIZE_32, 0, TEXGEN_POSITION, data);
//        }
      }
      ++idx;
    }
  }
}

void scrollTo(BigImage *img, int x, int y)
{
  int tileX;
  int tileY;
    
  if(x>=0)
  {
    tileX = x/32;
    img->sx = -(x%32);
  }
  else
  { 
    tileX = x/32 - 1;
    img->sx = (-x)%32 - 32;
  }
    
  if(y>=0)
  {  
    tileY = y/32;
    img->sy = -(y%32);
  }
  else
  {
    tileY = y/32 - 1;
    img->sy = (-y)%32 - 32;
  }

  while(img->tileX<tileX) scrollTilesLeft(img);
  while(img->tileX>tileX) scrollTilesRight(img);

  while(img->tileY<tileY) scrollTilesUp(img);
  while(img->tileY>tileY) scrollTilesDown(img);
}
